﻿using CoachingOrganizer.Logic.Helpers;
using CoachingOrganizer.Logic.Logic.Common;
using CoachingOrganizer.Toolkit.Events;
using CoachingOrganizer.Toolkit.Threading.CollectionsDecorators;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CoachingOrganizer.Logic.Models.Common
{
    public class PeriodModel
    {
        private readonly SimpleCollectionLoadDecorator<GoalModel> _goals;
        private GoalModel _currentGoal;
        private DateTime _startDate = DateTime.Today;
        private DateTime _finishDate = DateTime.Today.AddDays(7.0);

        public GoalModel CurrentGoal
        {
            get { return _currentGoal; }
            set
            {
                _currentGoal = value;
                OnCurrentGoalChanged();
            }
        }

        public IEnumerable<GoalModel> Goals
        {
            get { return _goals.Items; }
        }

        public DateTime StartDate
        {
            get { return _startDate; }
            set { _startDate = value; }
        }

        public DateTime FinishDate
        {
            get { return _finishDate; }
            set { _finishDate = value; }
        }

        public event EventHandler GoalsChanged
        {
            add { _goals.ItemsChanged += value; }
            remove { _goals.ItemsChanged -= value; }
        }

        public event NotifyCollectionChangedEventHandler GoalsCollectionChanged
        {
            add { _goals.ItemsCollectionChanged += value; }
            remove { _goals.ItemsCollectionChanged -= value; }
        }

        public event EventHandler CurrentGoalChanged;

        internal Func<ActionResult<IEnumerable<GoalLogic>>> EnumerateGoalsDelegate;

        internal Func<Action<CoachingOrganizer.ClientInfrastructure.ServicesEntities.LocalStorage.IGoalInfo>, ActionResult<GoalLogic>> AddNewGoalDelegate;

        internal Func<ActionResult> RemoveDelegate;

        internal Func<ActionResult> SaveDelegate;

        public PeriodModel()
        {
            _goals = new SimpleCollectionLoadDecorator<GoalModel>(EnumerateGoals);
        }

        public async Task LoadGoalsAsync(System.Threading.CancellationToken cancelLoad)
        {
            await Task.Run(() => _goals.FillItemsList(), cancelLoad);
        }

        public async Task<ActionResult> AddNewGoal(string title)
        {
            return await Task.Run(() =>
            {
                ActionResult<GoalModel> newGoalResult = UpdateHelper.GetModel(AddNewGoalDelegate, d => d.Title = title, l => l.Model);
                if (newGoalResult.IsValid)
                    _goals.ModifyCollection(col => col.Add(newGoalResult.Result));
                return newGoalResult.IsValid ? ActionResult.ValidResult : ActionResult.GetErrorResult(newGoalResult);
            });
        }

        public void ModifyGoalsCollection(Action<IList<GoalModel>> modificationDelegate)
        {
            _goals.ModifyCollection(modificationDelegate);
        }

        public async Task<ActionResult> Remove()
        {
            Func<ActionResult> removeDelegate = RemoveDelegate;
            return removeDelegate == null ? ActionResult.GetErrorResult(new NotSupportedException()) : await Task.Run(() => removeDelegate());
        }

        public async Task<ActionResult> Save()
        {
            Func<ActionResult> saveDelegate = SaveDelegate;
            return saveDelegate == null ? ActionResult.GetErrorResult(new NotSupportedException()) : await Task.Run(() => saveDelegate());
        }

        private ActionResult<IEnumerable<GoalModel>> EnumerateGoals()
        {
            return UpdateHelper.EnumerateModels(EnumerateGoalsDelegate, l => l.Model);
        }

        protected virtual void OnCurrentGoalChanged()
        {
            EventHandler handler = CurrentGoalChanged;
            if (handler != null)
                handler(this, EventArgs.Empty);
        }
    }
}
